package com.zmn.plat.business.impl.product;

import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dictionary.GlobalDict;
import com.zmn.common.dto.StatusDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.plat.business.interfaces.channel.ChannelServiceCategoryBService;
import com.zmn.plat.business.interfaces.product.ServProductBService;
import com.zmn.plat.common.constant.ProductConsts;
import com.zmn.plat.common.constant.ProductTitleConstants;
import com.zmn.plat.common.dictionary.PlatErrorCodeDict;
import com.zmn.plat.common.dto.category.AssSimpleCategoryDRO;
import com.zmn.plat.common.dto.product.base.ProductBaseDRO;
import com.zmn.plat.common.exception.PlatException;
import com.zmn.plat.common.util.IntegerStringToListUtil;
import com.zmn.plat.manager.dictionary.ProductDict;
import com.zmn.plat.model.dto.BaseCategoryAttributeDTO;
import com.zmn.plat.model.dto.product.ProductRelationDTO;
import com.zmn.plat.model.entity.category.BaseCategory;
import com.zmn.plat.model.entity.category.BaseCategoryAttribute;
import com.zmn.plat.model.entity.category.BaseCategoryAttributeEnum;
import com.zmn.plat.model.entity.category.BaseCategoryQuery;
import com.zmn.plat.model.entity.channel.ChannelIdAndName;
import com.zmn.plat.model.entity.product.*;
import com.zmn.plat.model.entity.product.guarantee.ProductGuarantee;
import com.zmn.plat.model.entity.servcategory.ServAssCategoryQuery;
import com.zmn.plat.model.entity.servcategory.ServCategory;
import com.zmn.plat.model.vo.product.*;
import com.zmn.plat.model.vo.product.tariff.item.ProductTariffGroupItemStatusVo;
import com.zmn.plat.model.vo.servcategory.BaseCategoryAttributeVO;
import com.zmn.plat.model.vo.servcategory.ServAssCategoryVO;
import com.zmn.plat.persistence.interfaces.product.ServProductDAO;
import com.zmn.plat.services.interfaces.area.BaseAreaService;
import com.zmn.plat.services.interfaces.category.BaseCategoryAttributeEnumService;
import com.zmn.plat.services.interfaces.category.BaseCategoryAttributeService;
import com.zmn.plat.services.interfaces.category.BaseCategoryService;
import com.zmn.plat.services.interfaces.channel.ChannelService;
import com.zmn.plat.services.interfaces.product.*;
import com.zmn.plat.services.interfaces.product.guarantee.ProductGuaranteeService;
import com.zmn.plat.services.interfaces.product.tariff.item.ProductTariffGroupItemService;
import com.zmn.plat.services.interfaces.servcategory.ServAssCategoryService;
import com.zmn.plat.services.interfaces.servcategory.ServCategoryService;
import com.zmn.plat.utils.bean.BeanCopyUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : tanghongjun
 * @since 2018/7/12 16:15
 */
@Service
@Slf4j
public class ServProductBServiceImpl implements ServProductBService {
    @Resource
    private ServProductService servProductService;
    @Resource
    protected ServProductAttributeService productAttributeService;
    @Resource
    protected ServProductAttributeValueService servProductAttributeValueService;
    @Resource
    protected BaseCategoryAttributeService baseCategoryAttributeService;
    @Resource
    protected BaseCategoryAttributeEnumService baseCategoryAttributeEnumService;
    @Resource
    protected ServProductDAO servProductDAO;
    @Resource
    protected ServProductRelationService servProductRelationService;
    @Resource
    protected ServTariffProductRelationService servTariffProductRelationService;
    @Resource
    protected BaseAreaService baseAreaService;
    @Resource
    protected ServCategoryService servCategoryService;
    @Resource
    protected BaseCategoryService baseCategoryService;
    @Resource
    protected FicoCategoryService ficoCategoryService;
    @Resource
    protected ProductTariffGroupItemService productFaultItemService;
    @Resource
    protected ServAssCategoryService servAssCategoryService;
    @Resource
    private ChannelServiceCategoryBService channelServiceCategoryBService;
    @Resource
    private ServProductPictureService servProductPictureService;
    @Resource
    private ProductGuaranteeService productGuaranteeService;
    @Resource
    private ChannelService channelService;

    @Override
    public String findBaseCategNameById(List<BaseCategory> baseCategorieall, Integer categId) {
        String name = "";
        if (NumberUtil.isNullOrZero(categId)) {
            return name;
        }
        BaseCategory baseCategory;

        for (int i = 0; i < baseCategorieall.size(); i++) {
            baseCategory = baseCategorieall.get(i);
            if (baseCategory.getCategId() == categId) {
                return baseCategory.getName();
            }
        }
        return name;
    }

    @Override
    public String findServCategNameById(List<ServCategory> servCategories, Integer categId, Integer showType) {
        String name = "";
        ServCategory servCategory;
        for (int i = 0; i < servCategories.size(); i++) {
            servCategory = servCategories.get(i);
            if (servCategory.getCategId().equals(categId)) {
                return Objects.equals(showType, ProductConsts.ERP_PRODUCT_TYPE) ? servCategory.getName() : servCategory.getShowName();
            }
        }
        return name;
    }

    @Override
    public List<BaseCategoryAttributeVO> findAttrById(Integer categOneId, Integer categId, Integer channelId) {
        List<BaseCategoryAttribute> attributes = baseCategoryAttributeService.listByCategoryId(categId, channelId);
        List<BaseCategoryAttribute> attributesAll = baseCategoryAttributeService.listByCategoryId(categOneId, channelId);
        attributesAll.addAll(attributes);

        List<BaseCategoryAttributeVO> items = new ArrayList<>();
        BaseCategoryAttribute attribute;
        BaseCategoryAttributeVO attributeVO;
        List<BaseCategoryAttributeEnum> attributeEnums;

        for (int i = 0; i < attributesAll.size(); i++) {
            attribute = attributesAll.get(i);
            attributeVO = new BaseCategoryAttributeVO();

            BeanUtils.copyProperties(attribute, attributeVO);
            attributeEnums = baseCategoryAttributeEnumService.listAttributeId(attribute.getAttrId());
            attributeVO.setBaseCategoryAttributeEnumList(attributeEnums);
            items.add(attributeVO);
        }
        return items;
    }

    @Override
    public String findFicoCategNameById(List<FicoCategory> ficoCategoryList, Integer ficoCtegId) {
        String name = "";
        FicoCategory ficoCategory;
        for (int i = 0; i < ficoCategoryList.size(); i++) {
            ficoCategory = ficoCategoryList.get(i);
            if (ficoCategory.getCategId().equals(ficoCtegId)) {
                return ficoCategory.getName();
            }
        }
        return name;
    }

    @Override
    public List<ServProduct> listById(Integer servCategId, Integer categOneId, Integer categId) {
        ServProductQuery query = new ServProductQuery();
        query.setStatus(GlobalConsts.YES);
        if (NumberUtil.isPositiveInteger(servCategId)) {
            query.setServCategId(servCategId);
        }
        if (NumberUtil.isPositiveInteger(categOneId)) {
            query.setCategOneId(categOneId);
        }
        if (NumberUtil.isPositiveInteger(categId)) {
            query.setCategId(categId);
        }
        List<ServProduct> servProducts = servProductService.listByQuery(query);
        return servProducts;
    }

    @Override
    public List<ServProduct> listByServCategIdAndCategOneIdAndCategIdAndChannelIdAndProductType(Integer servCategId, Integer categOneId, Integer categId, Integer channelId, Integer productType) {
        ServProductQuery query = new ServProductQuery();
        query.setStatus(GlobalConsts.YES);
        if (NumberUtil.isPositiveInteger(servCategId)) {
            query.setServCategId(servCategId);
        }
        if (NumberUtil.isPositiveInteger(categOneId)) {
            query.setCategOneId(categOneId);
        }
        if (NumberUtil.isPositiveInteger(categId)) {
            query.setCategId(categId);
        }
        query.setChannelId(channelId);
        query.setProductType(productType);
        List<ServProduct> servProducts = servProductService.listByQuery(query);
        return servProducts;
    }

    /**
     * 功能描述 ：后台产品下架的检查 规则：1 前台产品下架，那么不影响后续操作 2 前台产品上架，需要检查前台产品是否存在至少一个上架的后台产品 3.计价器产品下架，那么不影响后续操作 4 计价器产品上架，需要检查计价器产品是否存在至少一个上架的后台产品
     *
     * @param productIds
     * @return List<ServProduct>
     * @author tanbiao
     * @modifier
     * @since 2019/10/24
     */
    @Override
    public List<ServProductBackVO> listProductAndFilterByStatus(List<Integer> productIds, Integer showType) {
        List<ServProductBackVO> filterProducts = new ArrayList<>(1);
        // 前后台关联关系
        if (Objects.equals(showType, ProductConsts.EC_PRODUCT_TYPE)) {
            List<ServProductBackVO> relationProducts = servProductService.listByProductIds(productIds);
            filterProducts = filterBackProductsByStatus(relationProducts, productIds);
        }
        // 计价器关联关系
        else if (Objects.equals(showType, ProductConsts.ET_PRODUCT_TYPE)) {
            List<ServProductBackVO> tariffRelationProducts = servProductService.listTariffRelationBackProductsByProductIds(productIds);
            filterProducts = filterBackProductsByStatus(tariffRelationProducts, productIds);
        }
        return filterProducts;
    }

    private List<ServProductBackVO> filterBackProductsByStatus(List<ServProductBackVO> relationProducts, List<Integer> productIds) {
        Map<Integer, List<ServProductBackVO>> showProductsMap = new HashMap<>();
        Map<Integer, List<ServProductBackVO>> showProductIdRelationMap = new HashMap<>();
        List<ServProductBackVO> filteredProducts = new ArrayList<>();
        // 1.后台产品对应的前台产品关联的所有后台产品
        if (!CollectionUtils.isEmpty(relationProducts)) {
            // 按照前台产品进行分类
            relationProducts.forEach(e -> {
                // 1.未关联的情况下，返回值为空，不考虑此种情况
                // 2.前台产品下架的情况不考虑
                if (e.getShowProductId() != null && e.getShowStatus().equals(ProductDict.STATUS_ENABLE)) {
                    setToMap(showProductsMap, e);
                }
            });
            // 如果所有的后台产品均是下架状态，不考虑
            for (Map.Entry<Integer, List<ServProductBackVO>> entry : showProductsMap.entrySet()) {
                Integer key = entry.getKey();
                List<ServProductBackVO> values = entry.getValue();
                List<ServProductBackVO> enables = values.stream().filter(e -> e.getStatus().equals(ProductDict.STATUS_ENABLE)).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(enables)) {
                    showProductsMap.remove(key);
                }
            }
            // 以传入的id为依据检查是否是前台产品的最后一个上架的后台产品
            if (!showProductsMap.isEmpty()) {
                showProductsMap.forEach((showProductId, list) -> {
                    list.forEach(e -> {
                        if (productIds.contains(e.getProductId())) {
                            // 将对应的后台产品状态设置为“下架"，再次遍历集合，看是否还存在上架的后台产品，如果不存在，那么该后台产品不允许下架
                            e.setStatus(ProductDict.STATUS_DISABLE);
                            setToMap(showProductIdRelationMap, e);
                        }
                    });
                });
                // 再次遍历集合，查看是否存在启用状态的数据,如果不存在说明禁用之后不存在上架的后台产品
                showProductsMap.forEach((showProductId, list) -> {
                    List<ServProductBackVO> enables = list.stream().filter(e -> e.getStatus().equals(ProductDict.STATUS_ENABLE)).collect(Collectors.toList());
                    if (CollectionUtils.isEmpty(enables)) {
                        filteredProducts.addAll(showProductIdRelationMap.get(showProductId));
                    }
                });
            }
        }
        return filteredProducts;
    }

    private void setToMap(Map<Integer, List<ServProductBackVO>> showProductIdRelationMap, ServProductBackVO e) {
        if (showProductIdRelationMap.get(e.getShowProductId()) == null) {
            List<ServProductBackVO> relations = new ArrayList<>();
            relations.add(e);
            showProductIdRelationMap.put(e.getShowProductId(), relations);
        } else {
            showProductIdRelationMap.get(e.getShowProductId()).add(e);
        }
    }

    @Override
    public List<ServProduct> listByChannelIdAndServCategIdAndCategId(Integer channelId, Integer servCategId, Integer categId) {
        return servProductDAO.listByChannelIdAndServCategIdAndCategId(channelId, servCategId, categId);
    }

    @Override
    public List<ServProduct> listByChannelIdAndProductQuery(Integer channelId, ServProductQuery servProductQuery) {
        ServChannelProductQuery channelProductQuery = new ServChannelProductQuery();
        BeanUtils.copyProperties(servProductQuery, channelProductQuery);
        channelProductQuery.setChannelId(channelId);
        int count = servProductDAO.countByQuery(channelProductQuery);
        channelProductQuery.setTotalCount(count);
        return servProductDAO.listPageByQuery(channelProductQuery);
    }

    @Override
    public Integer countByChannelIdAndProductQuery(Integer channelId, ServProductQuery servProductQuery) {
        ServChannelProductQuery channelProductQuery = new ServChannelProductQuery();
        BeanUtils.copyProperties(servProductQuery, channelProductQuery);
        channelProductQuery.setChannelId(channelId);
        Integer count = servProductDAO.countByQuery(channelProductQuery);
        return count;
    }

    @Override
    public List<BaseCategoryAttributeDTO> getServProductOfAttribute(BaseCategory baseCategory) {
        List<BaseCategoryAttributeDTO> attributeViewS = new ArrayList<>();
        BaseCategoryAttribute baseCategoryAttribute = new BaseCategoryAttribute();
        List<BaseCategoryAttribute> attributeS = new ArrayList<>();

        // 判断传入参数是否为空
        if (baseCategory == null || baseCategory.getCategId() == 0) {
            return attributeViewS;
        }
        // 设置分类的ID
        baseCategoryAttribute.setCategId(baseCategory.getCategId());

        List<BaseCategoryAttributeEnum> attributeEnums;
        BaseCategoryAttributeEnum attributeEnum;
        BaseCategoryAttribute attribute;
        BaseCategoryAttributeDTO attributeView;

        for (int i = 0; i < attributeS.size(); i++) {
            attributeView = new BaseCategoryAttributeDTO();
            attribute = attributeS.get(i);
            attributeEnum = new BaseCategoryAttributeEnum();
            attributeEnum.setAttrId(attribute.getAttrId());
            attributeEnums = new ArrayList<>();

            // 把attribute的值给attributeView
            BeanUtils.copyProperties(attributeView, attribute);
            // 设置属性的值
            attributeView.setAttributeEnums(attributeEnums);
        }

        return attributeViewS;
    }

    @Override
    public Integer insert(ServProduct servProduct) {
        int pos = servProductService.insert(servProduct);
        return pos > 0 ? servProduct.getProductId() : 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer insertAll(ServProductVO servProductVO, String creater) {
        String attrEnums = servProductVO.getEnumIds();

        // 重复性验证，已存在产品返回2
        if (validateRepeat(servProductVO)) {
            return ProductDict.FLAG_ATTR_ERROR;
        }

        // 产品各级分类状态是否正常
        checkSingleProductStatus(servProductVO);

        // 1、所有通用产品名称不能重复；
        // 2、渠道产品名称与通用产品名称不能重复
        // 3、同一个渠道下的渠道产品名称不能重复
        // 4、渠道产品只能是后台，但是前台和计价器产品赋予了一个默认值，所以针对名称的重复性检查只考虑后台产品
        ServProductQuery query = new ServProductQuery();
        query.setOnlyName(servProductVO.getName());
        query.setShowType(servProductVO.getShowType());
        List<ServProduct> servProducts = servProductService.listByQuery(query);
        if (Objects.equals(servProductVO.getShowType(), ProductDict.ERP_PRODUCT_TYPE)) {
            if (Objects.equals(servProductVO.getProductType(), ProductDict.CURRENCY_PRODUCT)) {
                if (!CollectionUtils.isEmpty(servProducts)) {
                    // 1、所有通用产品名称不能重复；
                    List<ServProduct> currencyProducts = servProducts.stream().filter(e -> Objects.equals(e.getProductType(), ProductDict.CURRENCY_PRODUCT)).collect(Collectors.toList());
                    if (!CollectionUtils.isEmpty(currencyProducts)) {
                        return ProductDict.FLAG_NAME_ERROR;
                    }
                    // 2、渠道产品名称与通用产品名称不能重复
                    List<ServProduct> channelProducts = servProducts.stream().filter(e -> Objects.equals(e.getProductType(), ProductDict.CHANNEL_PRODUCT)).collect(Collectors.toList());
                    if (!CollectionUtils.isEmpty(channelProducts)) {
                        return ProductDict.FLAG_CHANNEL_PRODUCT_NAME_SAME_AS_PRODUCT_NAME_ERROR;
                    }
                }
            } else {
                // 2、渠道产品名称与通用产品名称不能重复
                List<ServProduct> currencyProducts = servProducts.stream().filter(e -> Objects.equals(e.getProductType(), ProductDict.CURRENCY_PRODUCT)).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(currencyProducts)) {
                    return ProductDict.FLAG_CHANNEL_PRODUCT_NAME_SAME_AS_PRODUCT_NAME_ERROR;
                }

                // 3、同一个渠道下的渠道产品名称不能重复
                if (checkchannelRepeat(servProductVO, servProducts)) {
                    return ProductDict.FLAG_CHANNEL_PRODUCT_NAME_ERROR;
                }
            }
        } else {
            // 非后台产品，同类型产品名称不能重复, 如果是前台默认产品则需要校验（一个前台服务分类+前台二级产品分类，只能设置一个默认产品）
            if (Objects.equals(ProductDict.EC_PRODUCT_TYPE, servProductVO.getShowType()) && Objects.equals(GlobalConsts.YES, servProductVO.getDefaultType())) {
                ServProductQuery defaultProductQuery = new ServProductQuery();
                defaultProductQuery.setShowType(servProductVO.getShowType());
                defaultProductQuery.setDefaultType(GlobalConsts.YES);
                defaultProductQuery.setServCategId(servProductVO.getServCategId());
                defaultProductQuery.setCategId(servProductVO.getCategId());
                List<ServProduct> defaultProducts = servProductService.listByQuery(defaultProductQuery);

                // 一个前台服务分类+前台二级产品分类，只能设置一个默认产品
                if (!CollectionUtils.isEmpty(defaultProducts)) {
                    return ProductDict.FLAG_DEFAULT_PRODUCT_EXIST_ERROR;
                }
            }

            if (!CollectionUtils.isEmpty(servProducts)) {
                return ProductDict.FLAG_NAME_ERROR;
            }
            // 3、同一个渠道下的渠道产品名称不能重复
            if (checkchannelRepeat(servProductVO, servProducts)) {
                return ProductDict.FLAG_CHANNEL_PRODUCT_NAME_ERROR;
            }
        }

        if (servProductVO.getShowType().equals(ProductConsts.ERP_PRODUCT_TYPE) && checkTariffName(servProductVO)) {
            return ProductDict.FLAG_TAFIFF_NAME_ERROR;
        }

        // 产品新增，计价器状态不允许为启用，因为此时没有关联价格表
        // 前台产品/计价器已经去掉了计价器状态显示，新增时默认计价器状态为开启，名称为""
        if (servProductVO.getShowType().equals(ProductConsts.ERP_PRODUCT_TYPE)) {
            if (servProductVO.getTariffStatus().equals(GlobalConsts.YES)) {
                throw new PlatException("产品新增，计价器状态不允许为启用，因为此时没有关联价格表");
            }
        }

        // 判断是否关联前台产品，如果没有则弹出提示语"后台产品上架必须关联前台产品"
        if (servProductVO.getShowType().equals(ProductConsts.ERP_PRODUCT_TYPE) && servProductVO.getStatus().equals(GlobalConsts.YES) && servProductVO.getShowProductId() == null) {
            throw new PlatException("后台产品上架必须关联前台产品");
        }

        if (servProductVO.getShowType().equals(ProductConsts.ERP_PRODUCT_TYPE)) {
            Integer flag = checkProductDisableStatus(servProductVO);
            if (flag > 0) {
                return flag;
            }

            checkRelatedProductGroup(servProductVO);
        }

        // 新增产品
        ServProduct servProduct = new ServProduct();
        BeanUtils.copyProperties(servProductVO, servProduct);
        servProduct.setCreater(creater);
        servProduct.setUpdater(creater);
        servProduct.setSequence(attrEnums);
        servProduct.setCreateTime(DateUtil.getNow());
        servProduct.setUpdateTime(DateUtil.getNow());
        servProduct.setCompanyId(Objects.isNull(servProduct.getCompanyId()) ? GlobalConsts.ZMN_COMPANY_ID : servProduct.getCompanyId());
        servProduct.setSort(Optional.of(servProductVO.getSort()).orElse(GlobalConsts.NONE));
        Integer productId = this.insert(servProduct);

        if (StringUtils.isNotEmpty(attrEnums)) {
            this.insertArrr(attrEnums, servProduct, creater);
        }
        // 添加前后台产品的关系
        if (ProductConsts.ERP_PRODUCT_TYPE.equals(servProduct.getShowType()) && Objects.nonNull(servProductVO.getShowProductId())) {
            ServProductRelation servProductRelation = new ServProductRelation();
            servProductRelation.setShowProductId(servProductVO.getShowProductId());
            servProductRelation.setProductId(productId);
            servProductRelation.setStatus(GlobalConsts.YES);
            servProductRelation.setCreateTime(new Date());
            servProductRelation.setCreater(creater);
            servProductRelationService.insert(servProductRelation);
        }

        // 添加后台产品与计价器产品的关联关系
        if (ProductConsts.ERP_PRODUCT_TYPE.equals(servProduct.getShowType()) && Objects.nonNull(servProductVO.getTariffProductId())) {
            ServTariffProductRelation servTariffProductRelation = new ServTariffProductRelation();
            servTariffProductRelation.setTariffProductId(servProductVO.getTariffProductId());
            servTariffProductRelation.setProductId(productId);
            servTariffProductRelation.setStatus(GlobalConsts.YES);
            servTariffProductRelation.setCreateTime(new Date());
            servTariffProductRelation.setCreater(creater);
            servTariffProductRelationService.insert(servTariffProductRelation);
        }

        // 成功返回1
        return ProductDict.FLAG_SUCCESS;
    }

    private Boolean checkchannelRepeat(ServProductVO servProductVO, List<ServProduct> servProducts) {
        // 修改时不做处理
        if (NumberUtil.isNotNullOrZero(servProductVO.getProductId())) {
            return false;
        }
        // 3、同一个渠道下的渠道产品名称不能重复
        List<Integer> oldChannelids = new ArrayList<>();
        servProducts.stream()
                .filter(x -> Objects.equals(x.getProductType(), ProductDict.CHANNEL_PRODUCT))
                .forEach(x -> oldChannelids.add(x.getChannelId()));
        if (oldChannelids.stream().filter(x -> Objects.equals(x, servProductVO.getChannelId())).count() > 0) {
            return true;
        }
        return false;
    }

    /**
     * 功能描述 :计价器名称是否重复
     *
     * @param servProductVO
     * @return boolean
     * @author tanbiao
     * @updater xiangjunming
     * @modifier
     * @since 2019/11/27
     * @since 20200109
     */
    private boolean checkTariffName(ServProductVO servProductVO) {
        ServProductQuery query = new ServProductQuery();
        query.setTariffName(servProductVO.getTariffName());
        query.setShowType(servProductVO.getShowType());
        if (servProductVO.getShowType() == ProductDict.ERP_PRODUCT_TYPE) {
            // 如果是后台产品则校验同服务分类和产品分类下计价器名称重复, 前台产品校验全局是否重复
            query.setServCategId(servProductVO.getServCategId());
            query.setCategOneId(servProductVO.getCategOneId());
            query.setCategId(servProductVO.getCategId());
        }

        List<ServProduct> productList = servProductService.listByQuery(query);
        if (!CollectionUtils.isEmpty(productList)) {
            if (productList.size() > 1) {
                return true;
            }
            // 同一类型产品的名称不能重复，因此最多只有一个
            ServProduct product = productList.get(0);
            if (!product.getProductId().equals(servProductVO.getProductId())) {
                return true;
            }
        }
        return false;
    }

    private void insertArrr(String attrEnums, ServProduct servProduct, String creater) {
        String[] arrtEnums = attrEnums.split(",");
        String attrEnumString;
        String[] attrEnumArr;

        for (int i = 0; i < arrtEnums.length; i++) {
            attrEnumString = arrtEnums[i];
            attrEnumArr = attrEnumString.split("&");
            // 新增产品属性
            ServProductAttribute servProductAttribute = new ServProductAttribute();
            BaseCategoryAttribute baseCategoryAttribute = baseCategoryAttributeService.findByKey(Integer.parseInt(attrEnumArr[0]));
            BeanUtils.copyProperties(baseCategoryAttribute, servProductAttribute);
            servProductAttribute.setProductId(servProduct.getProductId());
            servProductAttribute.setAttrName(baseCategoryAttribute.getName());
            servProductAttribute.setCreater(creater);
            servProductAttribute.setCreateTime(DateUtil.getNow());
            productAttributeService.insert(servProductAttribute);

            if (attrEnumArr.length == 1 || StringUtils.isEmpty(attrEnumArr[1]) || attrEnumArr[0].equals(attrEnumArr[1])) {
                continue;
            }

            // 新增产品属性值
            ServProductAttributeValue servProductAttributeValue = new ServProductAttributeValue();
            BaseCategoryAttributeEnum categoryAttributeEnum = baseCategoryAttributeEnumService.findByKey(Integer.parseInt(attrEnumArr[1]));
            BeanUtils.copyProperties(categoryAttributeEnum, servProductAttributeValue);
            servProductAttributeValue.setRelateId(servProductAttribute.getRelateId());
            servProductAttributeValueService.insert(servProductAttributeValue);
        }
    }

    private boolean validateRepeat(ServProductVO servProductVO) {
        ServProductQuery query = new ServProductQuery();

        // 如果全部为无属性，则不做控制,
        /**
         * 功能描述
         *
         * @author tanbiao
         * @since 2019/9/24
         * @modifier tanbiao 20190924 前台产品无属性不检查
         */
        if (ProductConsts.ERP_PRODUCT_TYPE.equals(servProductVO.getShowType())) {
            boolean flag = validateNoAttrValue(servProductVO.getEnumIds());
            if (flag) {
                query.setSequence(servProductVO.getEnumIds());
                query.setServCategId(servProductVO.getServCategId());
                query.setCategOneId(servProductVO.getCategOneId());
                query.setCategId(servProductVO.getCategId());
                int count = servProductService.countByQuery(query);
                if (count > 0) {
                    return true;
                }
            }
        }

        return false;
    }

    private boolean validateNoAttrValue(String enumIds) {
        String[] arrtEnums = enumIds.split(",");
        String attrEnumString;
        String[] attrEnumArr;

        for (int i = 0; i < arrtEnums.length; i++) {
            attrEnumString = arrtEnums[i];
            attrEnumArr = attrEnumString.split("&");
            if (attrEnumArr.length != 1 && StringUtils.isNotEmpty(attrEnumArr[1]) && !attrEnumArr[0].equals(attrEnumArr[1])) {
                return true;
            }
        }
        return false;
    }

    @Override
    public Integer updateStatus(Integer productId, Integer status, String updater) {
        ServProduct servProduct = new ServProduct();
        servProduct.setProductId(productId);
        servProduct.setStatus(status);
        servProduct.setUpdater(updater);
        return this.updateStatus(servProduct);
    }

    @Override
    public Integer updateStatus(ServProduct servProduct) {

        int pos = servProductService.updateStatus(servProduct);

        return pos;
    }

    @SuppressWarnings("Duplicates")
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer updateStatusBatch(List<Integer> productIds, Integer status, String updater, Integer showType) {
        checkProductStatus(productIds, status, showType);
        StatusDTO dto = new StatusDTO();
        dto.setIds(productIds);
        dto.setStatus(status);
        dto.setUpdater(updater);
        dto.setUpdateTime(new Date());

        return this.updateStatusBatch(dto);
    }

    @Override
    public Integer updateStatusBatch(StatusDTO dto) {

        int pos = servProductService.updateStatusBatch(dto);

        return pos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer updateAll(ServProductVO servProductVO, String updator) {
        List<ServProduct> servProductList = Collections.EMPTY_LIST;
        if (servProductVO.getShowType().equals(ProductConsts.ERP_PRODUCT_TYPE) && checkTariffName(servProductVO)) {
            return ProductDict.FLAG_TAFIFF_NAME_ERROR;
        }
        // 针对计价器为启用的情况进行检查
        if (servProductVO.getShowType().equals(ProductConsts.ERP_PRODUCT_TYPE) && servProductVO.getTariffStatus().equals(GlobalConsts.YES)) {
            Integer flag = checkTariffStatus(servProductVO);
            if (flag > 0) {
                return flag;
            }
        }

        // 产品分类状态检查
        checkSingleProductStatus(servProductVO);

        // 判断是否关联前台产品，如果没有则弹出提示语"后台产品上架必须关联前台产品"
        if (servProductVO.getShowType().equals(ProductConsts.ERP_PRODUCT_TYPE) && servProductVO.getStatus().equals(GlobalConsts.YES) && servProductVO.getShowProductId() == null) {
            throw new PlatException("后台产品上架必须关联前台产品");
        }

        // 修改需要做两层检查，变更关系之前的前台产品是否关联一个上架的后台产品，变更之后的前台产品是否关联一个上加的后台产品
        // 如果存在计价器产品，需要判断变更之前和变更之后是否关联一个上架的后台产品
        // 后台产品上架时添加校验：所属服务分类+二级产品分类是否关联产品组
        if (servProductVO.getShowType().equals(ProductConsts.ERP_PRODUCT_TYPE)) {
            Integer flag = checkProductDisableStatus(servProductVO);
            if (flag > 0) {
                return flag;
            }

            checkRelatedProductGroup(servProductVO);
        }


        /**
         * 功能描述
         *
         * @author tanbiao
         * @since 2019/9/24
         * @modifier tanbiao 20190924 前台产品不做属性检查
         */
        if (ProductConsts.ERP_PRODUCT_TYPE.equals(servProductVO.getShowType())) {
            // 如果全部为无属性，则不做控制
            boolean flag = validateNoAttrValue(servProductVO.getEnumIds());
            if (flag) {
                ServProductQuery query = new ServProductQuery();
                query.setSequence(servProductVO.getEnumIds());
                query.setServCategId(servProductVO.getServCategId());
                query.setCategOneId(servProductVO.getCategOneId());
                query.setCategId(servProductVO.getCategId());
                servProductList = servProductService.listByQuery(query);
                if (servProductList.size() > 1) {
                    return ProductDict.FLAG_ATTR_ERROR;
                }
                if (servProductList.size() == 1 && !servProductList.get(0).getProductId().equals(servProductVO.getProductId())) {
                    return ProductDict.FLAG_ATTR_ERROR;
                }
            }
        }

        // 名称检查
        // 1、所有通用产品名称不能重复；
        // 2、渠道产品名称与通用产品名称不能重复
        // 3、同一个渠道下的渠道产品名称不能重复
        // 4、渠道产品只能是后台，但是前台和计价器产品赋予了一个默认值，所以针对名称的重复性检查只考虑后台产品
        ServProductQuery query = new ServProductQuery();
        query.setOnlyName(servProductVO.getName());
        query.setShowType(servProductVO.getShowType());
        List<ServProduct> servProducts = servProductService.listByQuery(query);
        if (Objects.equals(servProductVO.getShowType(), ProductDict.ERP_PRODUCT_TYPE)) {
            if (Objects.equals(servProductVO.getProductType(), ProductDict.CURRENCY_PRODUCT)) {
                if (!CollectionUtils.isEmpty(servProducts)) {
                    // 1、所有通用产品名称不能重复；
                    List<ServProduct> currencyProducts = servProducts.stream()
                            .filter(e -> Objects.equals(e.getProductType(), ProductDict.CURRENCY_PRODUCT) && !Objects.equals(e.getProductId(), servProductVO.getProductId())).collect(Collectors.toList());
                    if (!CollectionUtils.isEmpty(currencyProducts)) {
                        return ProductDict.FLAG_NAME_ERROR;
                    }
                    // 2、渠道产品名称与通用产品名称不能重复
                    if (checkchannelRepeat(servProductVO, servProducts)) {
                        return ProductDict.FLAG_CHANNEL_PRODUCT_NAME_ERROR;
                    }
                }
            } else {
                // 2、渠道产品名称与通用产品名称不能重复
                List<ServProduct> currencyProducts = servProducts.stream().filter(e -> Objects.equals(e.getProductType(), ProductDict.CURRENCY_PRODUCT)).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(currencyProducts)) {
                    return ProductDict.FLAG_CHANNEL_PRODUCT_NAME_SAME_AS_PRODUCT_NAME_ERROR;
                }
                // 3、同一个渠道下的渠道产品名称不能重复
                if (checkchannelRepeat(servProductVO, servProducts)) {
                    return ProductDict.FLAG_CHANNEL_PRODUCT_NAME_ERROR;
                }
            }
        } else {
            // 非后台产品，同类型产品名称不能重复, 如果是前台默认产品则需要校验（一个前台服务分类+前台二级产品分类，只能设置一个默认产品）
            if (Objects.equals(ProductDict.EC_PRODUCT_TYPE, servProductVO.getShowType()) && Objects.equals(GlobalConsts.YES, servProductVO.getDefaultType())) {
                ServProductQuery defaultProductQuery = new ServProductQuery();
                defaultProductQuery.setShowType(servProductVO.getShowType());
                defaultProductQuery.setDefaultType(GlobalConsts.YES);
                defaultProductQuery.setServCategId(servProductVO.getServCategId());
                defaultProductQuery.setCategId(servProductVO.getCategId());
                List<ServProduct> defaultProducts = servProductService.listByQuery(defaultProductQuery);

                // 一个前台服务分类+前台二级产品分类，只能设置一个默认产品
                if (!CollectionUtils.isEmpty(defaultProducts)) {
                    defaultProducts = defaultProducts.stream().filter(e -> !Objects.equals(e.getProductId(), servProductVO.getProductId())).collect(Collectors.toList());
                    if (!CollectionUtils.isEmpty(defaultProducts)) {
                        return ProductDict.FLAG_DEFAULT_PRODUCT_EXIST_ERROR;
                    }
                }
            }

            if (!CollectionUtils.isEmpty(servProducts)) {
                servProducts = servProducts.stream().filter(e -> !Objects.equals(e.getProductId(), servProductVO.getProductId())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(servProducts)) {
                    return ProductDict.FLAG_NAME_ERROR;
                }
            }
        }

        String attrEnums = servProductVO.getEnumIds();

        // 更新产品
        ServProduct servProduct = new ServProduct();
        BeanUtils.copyProperties(servProductVO, servProduct);
        servProduct.setUpdater(updator);
        servProduct.setSequence(attrEnums);
        servProduct.setUpdateTime(DateUtil.getNow());
        servProduct.setSort(Optional.ofNullable(servProductVO.getSort()).orElse(GlobalConsts.NONE));
        servProductService.updateByKey(servProduct);
        this.deleteAttrByProductId(servProduct.getProductId());
        if (StringUtils.isNotEmpty(attrEnums)) {
            this.insertArrr(attrEnums, servProduct, updator);
        }

        if (ProductConsts.ERP_PRODUCT_TYPE.equals(servProduct.getShowType())) {
            ServProductRelationQuery relationQuery = new ServProductRelationQuery();
            relationQuery.setProductId(servProductVO.getProductId());
            List<ServProductRelation> relations = servProductRelationService.listByQuery(relationQuery);
            // 未关联的产品添加关联关系
            if (CollectionUtils.isEmpty(relations)) {
                // 添加前后台产品的关系
                ServProductRelation servProductRelation = new ServProductRelation();
                servProductRelation.setShowProductId(servProductVO.getShowProductId());
                servProductRelation.setProductId(servProductVO.getProductId());
                servProductRelation.setStatus(GlobalConsts.YES);
                servProductRelation.setCreateTime(new Date());
                servProductRelation.setCreater(updator);
                servProductRelationService.insert(servProductRelation);
            } else {
                ServProductRelation relation = relations.get(0);
                relation.setShowProductId(servProductVO.getShowProductId());
                servProductRelationService.updateByKey(relation);
            }
        }

        if (ProductConsts.ERP_PRODUCT_TYPE.equals(servProduct.getShowType())) {
            // 存在计价器产品id，建立关联关系，否则删除关联关系
            if (NumberUtil.isPositiveInteger(servProductVO.getTariffProductId())) {
                ServTariffProductRelationQuery tariffRelationQuery = new ServTariffProductRelationQuery();
                tariffRelationQuery.setProductId(servProductVO.getProductId());
                List<ServTariffProductRelation> relations = servTariffProductRelationService.listByQuery(tariffRelationQuery);
                // 未关联的产品添加关联关系
                if (CollectionUtils.isEmpty(relations)) {
                    // 添加加机器和后台产品的关系
                    if (!Objects.isNull(servProductVO.getTariffProductId())) {
                        ServTariffProductRelation servProductRelation = new ServTariffProductRelation();
                        servProductRelation.setTariffProductId(servProductVO.getTariffProductId());
                        servProductRelation.setProductId(servProductVO.getProductId());
                        servProductRelation.setStatus(GlobalConsts.YES);
                        servProductRelation.setCreateTime(new Date());
                        servProductRelation.setCreater(updator);
                        servTariffProductRelationService.insert(servProductRelation);
                    }
                } else {
                    if (!Objects.isNull(servProductVO.getTariffProductId())) {
                        ServTariffProductRelation relation = relations.get(0);
                        relation.setTariffProductId(servProductVO.getTariffProductId());
                        servTariffProductRelationService.updateByKey(relation);
                    }
                }
            } else {
                // 不存在计价器产品id，删除原有的关系
                servTariffProductRelationService.deleteByProductId(servProductVO.getProductId());
            }

        }
        // 成功返回1
        return ProductDict.FLAG_SUCCESS;
    }

    private void deleteAttrByProductId(Integer productId) {
        productAttributeService.deleteByProductId(productId);
        servProductAttributeValueService.deleteByProductId(productId);
    }

    private void checkSingleProductStatus(ServProductVO servProductVO) {
        ServCategory servCategory = servCategoryService.findByKey(servProductVO.getServCategId());
        BaseCategory baseCategoryOne = baseCategoryService.findByKey(servProductVO.getCategOneId());
        BaseCategory baseCategoryTwo = baseCategoryService.findByKey(servProductVO.getCategId());

        if (Objects.equals(GlobalConsts.YES, servProductVO.getStatus())) {
            if (Objects.equals(GlobalConsts.NO, baseCategoryTwo.getStatus())) {
                throw new PlatException("产品对应的二级产品分类状态需启用");
            }

            if (Objects.equals(GlobalConsts.NO, baseCategoryOne.getStatus())) {
                throw new PlatException("产品对应的一级产品分类状态需启用");
            }

            if (Objects.equals(ProductConsts.ERP_PRODUCT_TYPE, servProductVO.getShowType())) {
                if (servCategory == null || Objects.equals(GlobalConsts.NO, servCategory.getStatus())) {
                    throw new PlatException("产品对应的服务分类状态需启用");
                }
            } else if (Objects.equals(ProductConsts.EC_PRODUCT_TYPE, servProductVO.getShowType()) || Objects.equals(ProductConsts.ET_PRODUCT_TYPE, servProductVO.getShowType())) {
                if (servCategory == null || Objects.equals(GlobalConsts.NO, servCategory.getShowStatus())) {
                    throw new PlatException("产品对应的服务分类状态需启用");
                }
            }
        }
    }

    private void checkProductStatus(List<Integer> productIds, Integer status, Integer showType) {
        // 通用检查，各种产品类型上架的前提是服务分类产品分类必须上架
        if (Objects.equals(GlobalConsts.YES, status)) {
            List<ServProductStatusVO> productStatusVOS = servProductService.listProductStatusByProductIds(productIds);
            List<ServProductStatusVO> categTwoStatus = productStatusVOS.stream().filter(e -> Objects.equals(GlobalConsts.NO, e.getCategTwoStatus())).collect(Collectors.toList());
            List<ServProductStatusVO> categOneStatus = productStatusVOS.stream().filter(e -> Objects.equals(GlobalConsts.NO, e.getCategOneStatus())).collect(Collectors.toList());
            List<ServProductStatusVO> servCategStatus = productStatusVOS.stream().filter(e -> Objects.equals(GlobalConsts.NO, e.getServCategStatus())).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(categTwoStatus)) {
                StringBuilder stringBuilder = new StringBuilder();
                categTwoStatus.forEach(e -> stringBuilder.append(e.getName()).append(","));
                stringBuilder.deleteCharAt(stringBuilder.length() - 1);
                throw new PlatException("产品[" + stringBuilder.toString() + "]对应的二级产品分类状态需启用");
            }

            if (!CollectionUtils.isEmpty(categOneStatus)) {
                StringBuilder stringBuilder = new StringBuilder();
                categOneStatus.forEach(e -> stringBuilder.append(e.getName()).append(","));
                stringBuilder.deleteCharAt(stringBuilder.length() - 1);
                throw new PlatException("产品[" + stringBuilder.toString() + "]对应的一级产品分类状态需启用");
            }

            if (!CollectionUtils.isEmpty(servCategStatus)) {
                StringBuilder stringBuilder = new StringBuilder();
                servCategStatus.forEach(e -> stringBuilder.append(e.getName()).append(","));
                stringBuilder.deleteCharAt(stringBuilder.length() - 1);
                throw new PlatException("产品[" + stringBuilder.toString() + "]对应的服务分类状态需启用");
            }
        }

        if (Objects.equals(showType, ProductConsts.ERP_PRODUCT_TYPE)) {
            // 后台产品上架 需要判断是否关联前台产品，如果没有则提示“后台产品上架必须关联前台产品”；20191023
            // 后台产品上架时添加校验：所属服务分类+二级产品分类是否关联产品组 20210420
            if (ProductDict.STATUS_ENABLE == status) {
                List<ServProduct> relationProducts = servProductService.listProductHasRelated(productIds);
                String checkedProductIds = getProductIds(relationProducts);
                if (StringUtil.isNotBlank(checkedProductIds)) {
                    throw new PlatException("后台产品[" + checkedProductIds + "]上架必须关联前台产品！");
                }

                List<Integer> unRelatedProductGroupData = servProductService.listUnRelatedProductGroupByProductIdList(productIds);
                if (CollectionUtil.isNotNullOrEmpty(unRelatedProductGroupData)) {
                    throw new PlatException("后台产品[" + Joiner.on(",").join(unRelatedProductGroupData) + "]请先在分类关联中关联产品组再上架");
                }
            } else {
                // 后台产品下架需要判断相关联的上架状态的前台产品是否存在至少一个上架的后台产品；20191024
                // 后台产品下架需要判断相关联的上架状态的计价器产品是否存在至少一个上架的后台产品；20200406
                List<ServProductBackVO> relationProducts = listProductAndFilterByStatus(productIds, ProductConsts.EC_PRODUCT_TYPE);
                if (!CollectionUtils.isEmpty(relationProducts)) {
                    String checkedProductIds = getProductIds(relationProducts);
                    if (StringUtil.isNotBlank(checkedProductIds)) {
                        throw new PlatException("后台产品[" + checkedProductIds + "]对应的前台产品必须保留至少一个上架的后台产品！");
                    }
                }
                relationProducts = listProductAndFilterByStatus(productIds, ProductConsts.ET_PRODUCT_TYPE);
                if (!CollectionUtils.isEmpty(relationProducts)) {
                    String checkedProductIds = getProductIds(relationProducts);
                    if (StringUtil.isNotBlank(checkedProductIds)) {
                        throw new PlatException("后台产品[" + checkedProductIds + "]对应的计价器产品必须保留至少一个上架的后台产品！");
                    }
                }

            }
        }

    }

    private String getProductIds(List<? extends ServProduct> relationProducts) {
        if (!CollectionUtils.isEmpty(relationProducts)) {
            StringBuilder stringBuilder = new StringBuilder();
            relationProducts.forEach(e -> stringBuilder.append(e.getProductId()).append(","));
            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
            return stringBuilder.toString();
        }
        return null;
    }

    private void checkNewShowProductIsAviable(ServProductVO servProductVO, ServProduct showProduct) {
        // 新增，检查选中的前台产品是否合法
        if (Objects.equals(showProduct.getStatus(), GlobalConsts.YES)) {
            // 检查当前前台产品是否存在至少一个上架的后台产品
            List<ServProduct> list = servProductService.listBackProductByShowProductId(showProduct.getProductId());
            if (!CollectionUtils.isEmpty(list)) {
                ServProduct servProduct = new ServProduct();
                BeanUtils.copyProperties(servProductVO, servProduct);
                list.add(servProduct);
                list = list.stream().filter(e -> Objects.equals(e.getStatus(), GlobalConsts.YES)).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(list)) {
                    throw new PlatException("当前关联的前台产品至少关联一个上架的后台产品");
                }
            }
        }
    }

    private void checkNewTariffProductIsAviable(ServProductVO servProductVO, ServProduct tariffProduct) {
        // 新增，检查选中的前台产品是否合法
        if (Objects.equals(tariffProduct.getStatus(), GlobalConsts.YES)) {
            // 检查当前前台产品是否存在至少一个上架的后台产品
            List<ServProduct> list = servProductService.listBackProductByTariffProductId(tariffProduct.getProductId());
            if (!CollectionUtils.isEmpty(list)) {
                ServProduct servProduct = new ServProduct();
                BeanUtils.copyProperties(servProductVO, servProduct);
                list.add(servProduct);
                list = list.stream().filter(e -> Objects.equals(e.getStatus(), GlobalConsts.YES)).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(list)) {
                    throw new PlatException("当前关联的计价器产品至少关联一个上架的后台产品");
                }
            }
        }
    }

    private void checkRelatedProductGroup(ServProductVO servProductVO) {
        Integer servCategId = servProductVO.getServCategId();
        Integer categId = servProductVO.getCategId();
        Integer status = servProductVO.getStatus();

        if (Objects.equals(GlobalConsts.YES, status)) {
            ServAssCategoryQuery query = new ServAssCategoryQuery();
            query.setServCategId(servCategId);
            query.setCategId(categId);
            List<ServAssCategoryVO> list = servAssCategoryService.listByQuery(query);
            list = list.stream().filter(e -> Objects.nonNull(e.getProductGroupcId()) && Objects.nonNull(e.getProductGroupfId()) && Objects.nonNull(e.getProductGroupbId())).collect(Collectors.toList());
            if (CollectionUtil.isNullOrEmpty(list)) {
                throw new PlatException("请先在分类关联中关联产品组再上架");
            }
        }
    }

    private Integer checkProductDisableStatus(ServProductVO servProductVO) {
        Integer flag = 0;
        // 计价器状态和前台产品状态为禁用的不做处理
        // 前台产品必选
        ServProduct showProduct = servProductService.findByKey(servProductVO.getShowProductId());
        if (Objects.isNull(showProduct)) {
            throw new PlatException("前台产品不存在");
        }
        // 检查新选中的前台产品是否合法
        checkNewShowProductIsAviable(servProductVO, showProduct);
        // 修改
        if (NumberUtil.isPositiveInteger(servProductVO.getProductId())) {
            // 修改，检查修改之前的前台产品在修改之后是否存在上架的后台产品
            ServProductRelation servProductRelation = servProductRelationService.findByProductId(servProductVO.getProductId());
            if (!Objects.isNull(servProductRelation)) {
                ServProduct oldShowProduct = servProductService.findByKey(servProductRelation.getShowProductId());
                // 原来关联的前台产品为启用的做检查
                if (!Objects.isNull(oldShowProduct) && Objects.equals(oldShowProduct.getStatus(), GlobalConsts.YES)) {
                    // 存在修改前台产品
                    boolean isThesameShowProduct = Objects.equals(servProductVO.getShowProductId(), oldShowProduct.getProductId());
                    // 存在修改计价器产品
                    if ((isThesameShowProduct && Objects.equals(servProductVO.getStatus(), GlobalConsts.NO)) || !isThesameShowProduct) {
                        List<ServProduct> list = servProductService.listBackProductByShowProductId(oldShowProduct.getProductId());
                        // 排除当前的数据是否还存在启用的后台产品
                        list =
                                list.stream().filter(e -> Objects.equals(e.getStatus(), GlobalConsts.YES) && !Objects.equals(e.getProductId(), servProductVO.getProductId())).collect(Collectors.toList());
                        if (CollectionUtils.isEmpty(list)) {
                            throw new PlatException("原关联的前台产品至少关联一个上架的后台产品");
                        }
                    }
                }
            }

        }

        // 计价器产品可选
        ServProduct tariffProduct = null;
        if (NumberUtil.isPositiveInteger(servProductVO.getTariffProductId())) {
            tariffProduct = servProductService.findByKey(servProductVO.getTariffProductId());
            if (Objects.isNull(showProduct)) {
                throw new PlatException("计价器产品不存在");
            }
            // 新的计价器产品是否合法
            checkNewTariffProductIsAviable(servProductVO, tariffProduct);
        }

        // 修改
        if (NumberUtil.isPositiveInteger(servProductVO.getProductId())) {
            // 原来存在，现在不存在；原来不存在，现在存在；都不存在；都存在；
            // 修改，检查修改之前的前台产品在修改之后是否存在上架的后台产品
            ServTariffProductRelation servTariffProductRelation = servTariffProductRelationService.findByProductId(servProductVO.getProductId());
            if (!Objects.isNull(servTariffProductRelation)) {
                ServProduct oldTariffProduct = servProductService.findByKey(servTariffProductRelation.getTariffProductId());
                // 原来关联的前台产品为启用的做检查
                if (!Objects.isNull(oldTariffProduct) && Objects.equals(oldTariffProduct.getStatus(), GlobalConsts.YES)) {
                    boolean isThesameTariffProduct = Objects.equals(servProductVO.getTariffProductId(), oldTariffProduct.getProductId());
                    // 存在修改计价器产品
                    if ((isThesameTariffProduct && Objects.equals(servProductVO.getStatus(), GlobalConsts.NO)) || !isThesameTariffProduct) {
                        List<ServProduct> list = servProductService.listBackProductByTariffProductId(oldTariffProduct.getProductId());
                        // 排除当前的数据是否还存在启用的后台产品
                        list =
                                list.stream().filter(e -> Objects.equals(e.getStatus(), GlobalConsts.YES) && !Objects.equals(e.getProductId(), servProductVO.getProductId())).collect(Collectors.toList());
                        if (CollectionUtils.isEmpty(list)) {
                            throw new PlatException("原关联的计价器产品至少关联一个上架的后台产品");
                        }
                    }
                }
            }
        }
        return flag;
    }

    /**
     * 功能描述 :修改产品计价器状态，校验计价器相关设置是否合法，返回服务分类，产品一二级分类和价格表相应数据的状态
     *
     * @return 校验结果代码
     * @author tanbiao
     * @modifier
     * @since 2020/3/11
     */
    private Integer checkTariffStatus(ServProductVO servProductVO) {
        Integer flag = 0;

        // 后台产品关联的前台产品是否为上架状态
        Integer showProductId = servProductVO.getShowProductId();
        ServProduct servProduct = servProductService.findByKey(showProductId);
        Integer tariffProductId = servProductVO.getTariffProductId();
        if (servProduct == null || servProduct.getStatus() != GlobalConsts.YES) {
            throw new PlatException("若要启用计价器状态，请先上架该产品关联的前台产品");
        }

        // 后台产品关联的计价器是上架状态
        ServProduct tariffProduct = servProductService.findByKey(tariffProductId);
        if (tariffProduct == null || tariffProduct.getStatus() != GlobalConsts.YES) {
            throw new PlatException("若要启用计价器状态，请先上架该产品关联的计价器产品");
        }

        List<ProductTariffGroupItemStatusVo> list = productFaultItemService.listProductTariffStatusByProductIdAndShowType(servProductVO.getProductId(), servProductVO.getShowType());

        // 启用中的保外计价器价格表价至少有一个启用中的项目
        List<ProductTariffGroupItemStatusVo> enableItemStatusList = list.stream().filter(e -> e.getItemStatus() != null && e.getItemStatus().equals(GlobalConsts.YES)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(enableItemStatusList)) {
            throw new PlatException("请设置该产品的保外计价器价格表：价格表为启用状态并且有启用中的项目，请先设置");
        }
        return flag;
    }

    @SuppressWarnings("Duplicates")
    @Override
    public List<ServProductVO> listShowVOPageByQuery(ServProductQuery query, List<ServCategory> servCategories, List<BaseCategory> baseCategorieall) {

        // 添加了后台产品的查询条件，修改查询Sql
        int count = servProductService.countByQueryForShow(query);
        query.setTotalCount(count);
        List<ServProduct> servProducts = servProductService.listPageByQueryForShow(query);
        return this.translateShowCategName(servProducts, servCategories, baseCategorieall);
    }

    @SuppressWarnings("Duplicates")
    @Override
    public List<ServProductVO> listTariffVOPageByQuery(ServProductQuery query, List<ServCategory> servCategories, List<BaseCategory> baseCategorieall) {
        // 添加了后台产品的查询条件，修改查询Sql
        int count = servProductService.countByQueryForTariff(query);
        query.setTotalCount(count);
        List<ServProduct> servProducts = servProductService.listPageByQueryForTariff(query);
        return this.translateShowCategName(servProducts, servCategories, baseCategorieall);
    }

    /**
     * 描述: 按照服务分类、一级分类、二级分类、产品的排序号升序排 查询前台产品（导出的时候用）
     *
     * @param query            产品查询Query
     * @param baseCategorieall 产品分类集合
     * @param servCategories   服务分类集合
     * @return
     * @auther tanghongjun
     * @since 2020/3/3 16:51
     */
    @SuppressWarnings("Duplicates")
    public List<ServProductVO> listShowVOPageByQueryByCategSort(ServProductQuery query, List<ServCategory> servCategories, List<BaseCategory> baseCategorieall) {
        // 添加了后台产品的查询条件，修改查询Sql
        int count = servProductService.countByQueryForShow(query);
        query.setTotalCount(count);
        List<ServProduct> servProducts = servProductService.listPageByQueryForShowByCategSort(query);
        return this.translateShowCategName(servProducts, servCategories, baseCategorieall);
    }

    /**
     * 描述: 按照服务分类、一级分类、二级分类、产品的排序号升序排 查询前台产品（导出的时候用）
     *
     * @param query            产品查询Query
     * @param baseCategorieall 产品分类集合
     * @param servCategories   服务分类集合
     * @return
     * @auther tanghongjun
     * @since 2020/3/3 16:51
     */
    @SuppressWarnings("Duplicates")
    public List<ServProductVO> listTariffVOPageByQueryByCategSort(ServProductQuery query, List<ServCategory> servCategories, List<BaseCategory> baseCategorieall) {
        // 添加了后台产品的查询条件，修改查询Sql
        int count = servProductService.countByQueryForTariff(query);
        query.setTotalCount(count);
        List<ServProduct> servProducts = servProductService.listPageByQueryForTariffByCategSort(query);
        return this.translateShowCategName(servProducts, servCategories, baseCategorieall);
    }

    /**
     * 描述: 按照服务分类、一级分类、二级分类、产品的排序号升序排 查询后台产品（导出的时候用）
     *
     * @param query            产品查询Query
     * @param baseCategorieall 产品分类集合
     * @param servCategories   服务分类集合
     * @return
     * @auther tanghongjun
     * @since 2020/3/3 16:51
     */
    @SuppressWarnings("Duplicates")
    public List<ServProductVO> listVOPageByQueryByCategSort(ServProductQuery query, List<ServCategory> servCategories, List<BaseCategory> baseCategorieall) {

        // 添加了后台产品的查询条件，修改查询Sql
        int count = servProductService.countByQueryForBackProduct(query);
        query.setTotalCount(count);
        List<ServProductBackVO> servProducts = servProductService.listPageByQueryForBackProductByCategSort(query);
        return this.translateBackCategName(servProducts, servCategories, baseCategorieall);
    }

    private List<ServProductVO> translateShowCategName(List<ServProduct> servProducts, List<ServCategory> servCategories, List<BaseCategory> baseCategorieall) {
        List<ServProductVO> items = new ArrayList<>();
        Map<Integer, String> channelMaps = new HashMap<>();
        List<Integer> channelids = new ArrayList<>();
        for (ServProduct x : servProducts) {
            if (NumberUtil.isNotNullOrZero(x.getChannelId())) {
                channelids.add(x.getChannelId());

            }
        }
        channelids = channelids.stream().distinct().collect(Collectors.toList());
        if (CollectionUtil.isNotNullOrEmpty(channelids)) {
            List<ChannelIdAndName> channelIdAndNames = channelService.listNameByChannelIds(channelids);
            channelMaps = channelIdAndNames.stream().collect(Collectors.toMap(ChannelIdAndName::getChannelId, ChannelIdAndName::getName));
        }
        ServProductVO servProductView;
        ServProduct servProduct;
        for (int i = 0; i < servProducts.size(); i++) {
            servProduct = servProducts.get(i);
            servProductView = new ServProductVO();
            BeanUtils.copyProperties(servProduct, servProductView);

            servProductView.setServCategName(this.findServCategNameById(servCategories, servProduct.getServCategId(), servProduct.getShowType()));
            servProductView.setCategOneName(this.findBaseCategNameById(baseCategorieall, servProduct.getCategOneId()));
            servProductView.setCategName(this.findBaseCategNameById(baseCategorieall, servProduct.getCategId()));
            servProductView.setChannelName(channelMaps.get(servProduct.getChannelId()));
            if (StringUtils.isNotEmpty(servProduct.getBizType())) {
                servProductView.setBizTypeStr(servProductService.translateBizTypeStrByBizType(servProduct.getBizType()));
            }
            items.add(servProductView);
        }
        return items;
    }

    private List<ServProductVO> translateBackCategName(List<ServProductBackVO> servProducts, List<ServCategory> servCategories, List<BaseCategory> baseCategorieall) {
        List<ServProductVO> items = new ArrayList<>();

        ServProductVO servProductView;
        ServProductBackVO servProduct;

        for (int i = 0; i < servProducts.size(); i++) {
            servProduct = servProducts.get(i);
            servProductView = new ServProductVO();
            BeanUtils.copyProperties(servProduct, servProductView);

            servProductView.setServCategName(this.findServCategNameById(servCategories, servProduct.getServCategId(), servProduct.getShowType()));
            servProductView.setCategOneName(this.findBaseCategNameById(baseCategorieall, servProduct.getCategOneId()));
            servProductView.setCategName(this.findBaseCategNameById(baseCategorieall, servProduct.getCategId()));
            if (StringUtils.isNotEmpty(servProduct.getShowPlat())) {
                servProductView.setShowPlatStr(servProductService.translateShowPlatStrByShowPlat(servProduct.getShowPlat()));
            }
            items.add(servProductView);
        }
        return items;
    }

    /**
     * 描述: 根据条件导出后台产品报表
     *
     * @param query 查询条件
     * @return java.util.ArrayList<java.util.List>
     * @author wangjie
     * @updater wangjie 2019-11-07 导出添加银联支付状态列
     * @since 14:49 2019/2/19
     **/
    @Override
    public ArrayList<List> outputProductExcel(ServProductQuery query) {
        // 服务分类
        ServCategory querySC = new ServCategory();
        List<ServCategory> servCategories = servCategoryService.listByQuery(querySC);

        // 产品分类
        BaseCategoryQuery queryB = new BaseCategoryQuery();
        queryB.setShowType(query.getShowType());
        List<BaseCategory> baseCategorieall = baseCategoryService.listByQuery(queryB);

        // query.setPageSize(10000);
        List<ServProductVO> servProductVOList = this.listVOPageByQueryByCategSort(query, servCategories, baseCategorieall);
        ArrayList<List> arrayList = Lists.newArrayListWithExpectedSize(servProductVOList.size() + 1);
        List<String> column = Arrays.asList(ProductConsts.ZMN_PRODUCT_EXCEL_TITLE);
        arrayList.add(column);

        if (!servProductVOList.isEmpty()) {
            servProductVOList.forEach(servProductVO -> {
                List<String> item = new ArrayList<>();
                item.add(servProductVO.getServCategName());
                item.add(servProductVO.getCategOneName());
                item.add(servProductVO.getCategName());
                item.add(servProductVO.getProductId().toString());
                item.add(servProductVO.getName());
                item.add(servProductVO.getShowProductName());
                // 产品类型
                item.add(Objects.isNull(servProductVO.getProductType()) ? "" : ProductDict.getProductType(servProductVO.getProductType()));
                // 渠道名称
                item.add(servProductVO.getChannelName());
                // 展示平台
                item.add(servProductVO.getShowPlatStr());
                item.add(servProductVO.getUnit());
                // 状态
                item.add(Objects.isNull(servProductVO.getStatus()) ? "" : GlobalDict.getShelveStatus(servProductVO.getStatus()));
                item.add(servProductVO.getTariffName());
                // 计价器状态
                item.add(Objects.isNull(servProductVO.getTariffStatus()) ? "" : GlobalDict.getShelveStatus(servProductVO.getTariffStatus()));
                arrayList.add(item);
            });
        }
        return arrayList;
    }

    /**
     * 描述: 根据条件导出前台报表
     *
     * @param query 查询条件
     * @return java.util.ArrayList<java.util.List>
     * @author wangjie
     * @updater wangjie 2019-11-07 导出添加银联支付状态列
     * @since 14:49 2019/2/19
     **/
    @Override
    public ArrayList<List> outputShowProductExcel(ServProductQuery query) {
        // 服务分类
        ServCategory querySC = new ServCategory();
        List<ServCategory> servCategories = servCategoryService.listByQuery(querySC);

        // 产品分类
        BaseCategoryQuery queryB = new BaseCategoryQuery();
        queryB.setShowType(ProductConsts.EC_PRODUCT_TYPE);
        List<BaseCategory> baseCategorieall = baseCategoryService.listByQuery(queryB);

        // query.setPageSize(10000);
        List<ServProductVO> servProductVOList = this.listShowVOPageByQueryByCategSort(query, servCategories, baseCategorieall);
        ArrayList<List> arrayList = Lists.newArrayListWithExpectedSize(servProductVOList.size() + 1);
        List<String> column = Arrays.asList(ProductConsts.ZMN_SHOW_PRODUCT_EXCEL_TITLE);
        arrayList.add(column);

        if (!servProductVOList.isEmpty()) {
            servProductVOList.forEach(servProductVO -> {
                List<String> item = new ArrayList<>();
                item.add(servProductVO.getServCategName());
                item.add(servProductVO.getCategOneName());
                item.add(servProductVO.getCategName());
                item.add(servProductVO.getProductId().toString());
                item.add(servProductVO.getName());
                item.add(servProductVO.getShowPlatStr());
                item.add(servProductVO.getUnit());
                // 状态
                item.add(Objects.isNull(servProductVO.getStatus()) ? "" : GlobalDict.getShelveStatus(servProductVO.getStatus()));
                arrayList.add(item);
            });
        }
        return arrayList;
    }

    /**
     * 描述: 根据条件导出前台报表
     *
     * @param query 查询条件
     * @return java.util.ArrayList<java.util.List>
     * @author wangjie
     * @updater wangjie 2019-11-07 导出添加银联支付状态列
     * @since 14:49 2019/2/19
     **/
    @Override
    public ArrayList<List> outputTariffProductExcel(ServProductQuery query) {
        // 服务分类
        ServCategory querySC = new ServCategory();
        List<ServCategory> servCategories = servCategoryService.listByQuery(querySC);

        // 产品分类
        BaseCategoryQuery queryB = new BaseCategoryQuery();
        queryB.setShowType(ProductConsts.EC_PRODUCT_TYPE);
        List<BaseCategory> baseCategorieall = baseCategoryService.listByQuery(queryB);

        // query.setPageSize(10000);
        List<ServProductVO> servProductVOList = this.listTariffVOPageByQueryByCategSort(query, servCategories, baseCategorieall);
        ArrayList<List> arrayList = Lists.newArrayListWithExpectedSize(servProductVOList.size() + 1);
        List<String> column = Arrays.asList(ProductConsts.ZMN_SHOW_PRODUCT_EXCEL_TITLE);
        arrayList.add(column);

        if (!servProductVOList.isEmpty()) {
            servProductVOList.forEach(servProductVO -> {
                List<String> item = new ArrayList<>();
                item.add(servProductVO.getServCategName());
                item.add(servProductVO.getCategOneName());
                item.add(servProductVO.getCategName());
                item.add(servProductVO.getProductId().toString());
                item.add(servProductVO.getName());
                item.add(servProductVO.getShowPlatStr());
                item.add(servProductVO.getUnit());
                // 状态
                item.add(Objects.isNull(servProductVO.getStatus()) ? "" : GlobalDict.getShelveStatus(servProductVO.getStatus()));
                arrayList.add(item);
            });
        }
        return arrayList;
    }

    @Override
    public List<AssSimpleCategoryDRO> listAssSimpleCategByShowProductId(Integer showProductId) {
        if (NumberUtil.isNullOrZero(showProductId)) {
            log.error("showProductId is not valiable.showProductId={}", showProductId);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        ServProductRelationQuery query = new ServProductRelationQuery();
        query.setShowProductId(showProductId);
        List<ServProductRelation> productRelationList = servProductRelationService.listByQuery(query);
        if (CollectionUtils.isEmpty(productRelationList)) {
            log.error("前后台产品的关联关系不存在。showProductId={},errorCode:{}", showProductId, PlatErrorCodeDict.ERROR_CODE_SERCATEGORY_PRODUCT_RELATIONSHIP_NOT_EXISTS);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_SERCATEGORY_PRODUCT_RELATIONSHIP_NOT_EXISTS);
        }

        List<Integer> productIds = productRelationList.stream().map(ServProductRelation::getProductId).distinct().collect(Collectors.toList());

        if (CollectionUtils.isEmpty(productIds)) {
            log.error("前后台产品对应的后台产品不存在。showProductId={},errorCode:{}", showProductId, PlatErrorCodeDict.ERROR_CODE_SERCATEGORY_PRODUCT_RELATIONSHIP_NOT_EXISTS);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_SERCATEGORY_PRODUCT_RELATIONSHIP_NOT_EXISTS);
        }

        ServProductQuery servProductQuery = new ServProductQuery();
        servProductQuery.setProductIds(productIds);
        servProductQuery.setStatus(GlobalConsts.YES);
        List<ServProduct> servProductList = servProductService.listByQuery(servProductQuery);

        if (CollectionUtils.isEmpty(servProductList)) {
            log.error("前后台产品无启用的后台产品。showProductId={},errorCode:{}", showProductId, PlatErrorCodeDict.ERROR_CODE_SERCATEGORY_SHOWPRODUCT_DOESNOT_HAVE_VALIABLE_PRODUCT);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_SERCATEGORY_SHOWPRODUCT_DOESNOT_HAVE_VALIABLE_PRODUCT);
        }

        List<AssSimpleCategoryDRO> dros = servProductList.stream().map(servProduct -> new AssSimpleCategoryDRO(servProduct.getServCategId(), servProduct.getCategOneId(), servProduct.getCategId()))
                .distinct().collect(Collectors.toList());

        return dros;
    }

    @Override
    public List<ProductBaseDRO> listProductByProductIdAndStatus(Integer productId, Integer status) {
        if (NumberUtil.isNullOrZero(productId)) {
            log.error("产品ID不能为空，productId={}", productId);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }
        ServProductRelationQuery query = new ServProductRelationQuery();
        query.setProductId(productId);
        List<ServProductRelation> productRelationList = servProductRelationService.listByQuery(query);
        if (CollectionUtils.isEmpty(productRelationList)) {
            log.error("产品关联关系不存在，query={}", query);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PRODUCT_PRODUCT_NO_DATA);
        }
        List<Integer> showProductIds = productRelationList.stream().map(ServProductRelation::getShowProductId).collect(Collectors.toList());
        List<ServProduct> servProductList = servProductService.listByIdList(showProductIds, status);
        return this.returnProductDro(servProductList);
    }

    @Override
    public List<ProductBaseDRO> listProductByShowProductIdAndStatusAndChannelIdAndProductType(Integer showProductId, Integer status, Integer channelId, Integer productType) {
        if (NumberUtil.isNullOrZero(showProductId)) {
            log.error("产品ID不能为空，productId={}", showProductId);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        ServProductRelationQuery query = new ServProductRelationQuery();
        query.setShowProductId(showProductId);
        List<ServProductRelation> productRelationList = servProductRelationService.listByQuery(query);

        if (CollectionUtils.isEmpty(productRelationList)) {
            log.error("产品关联关系不存在，query={}", query);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PRODUCT_PRODUCT_NO_DATA);
        }

        // 判断渠道是否开通分类，如果已开通则取当前渠道，反之取上级渠道信息
        try {
            if (NumberUtil.isPositiveInteger(channelId)) {
                channelId = channelServiceCategoryBService.getAvailableCategoryChannelId(channelId);
            }
        } catch (PlatException e) {
            return Collections.emptyList();
        }

        List<Integer> productIds = productRelationList.stream().map(ServProductRelation::getProductId).distinct().collect(Collectors.toList());
        ServProductQuery servProductQuery = new ServProductQuery();
        servProductQuery.setProductIds(productIds);
        servProductQuery.setStatus(status);
        servProductQuery.setChannelId(channelId);
        servProductQuery.setProductType(productType);
        List<ServProduct> servProductList = servProductService.listByQuery(servProductQuery);
        return this.returnProductDro(servProductList);
    }

    @Override
    @Cacheable(cacheNames = "redis1h", key = "'productRelation:productIdList:'+#p0+':showType:'+#p1", unless = "#result == null")
    public List<ProductRelationDTO> listProductRalationByIdListAndShowType(List<Integer> productIdList, Integer showType) {
        List<ProductRelationDTO> relationDTOList = servProductService.listProductRalationByIdListAndShowType(productIdList, showType);
        // 将额外信息加入实体中，方便后续的数据翻译
        if (!CollectionUtils.isEmpty(relationDTOList)) {
            Set<Integer> servCategIdList = new HashSet<>();
            Set<Integer> categIds = new HashSet<>();
            relationDTOList.stream().forEach(e -> {
                servCategIdList.add(e.getServCategId());
                servCategIdList.add(e.getShowServCategId());
                categIds.add(e.getCategOneId());
                categIds.add(e.getCategId());
                categIds.add(e.getShowCategOneId());
                categIds.add(e.getShowCategId());
            });
            List<ServCategory> servCategories = servCategoryService.findByKeys(new ArrayList<>(servCategIdList));
            Map<Integer, String> servCategMap = servCategories.stream().collect(Collectors.toMap(e -> e.getCategId(), e -> e.getName(), (k, v) -> k));
            Map<Integer, String> showServCategMap = servCategories.stream().collect(Collectors.toMap(e -> e.getCategId(), e -> e.getShowName(), (k, v) -> k));
            List<BaseCategory> categoryList = baseCategoryService.findByKeys(new ArrayList<>(categIds));
            Map<Integer, String> categMap = categoryList.stream().collect(Collectors.toMap(e -> e.getCategId(), e -> e.getName(), (k, v) -> k));
            relationDTOList.forEach(e -> {
                e.setServCategName(servCategMap.get(e.getServCategId()));
                e.setShowServCategName(showServCategMap.get(e.getShowServCategId()));
                e.setCategOneName(categMap.get(e.getCategOneId()));
                e.setShowCategOneName(categMap.get(e.getShowCategOneId()));
                e.setCategName(categMap.get(e.getCategId()));
                e.setShowCategName(categMap.get(e.getShowCategId()));
            });
        }
        return relationDTOList;
    }

    private List<ProductBaseDRO> returnProductDro(List<ServProduct> servProducts) {
        ProductBaseDRO productBaseDRO;
        List<ProductBaseDRO> productBaseDROList = new ArrayList<>();

        BaseCategoryQuery queryB = new BaseCategoryQuery();
        List<BaseCategory> baseCategorieall = baseCategoryService.listByQuery(queryB);

        ServCategory querySC = new ServCategory();
        List<ServCategory> servCategories = servCategoryService.listByQuery(querySC);

        BeanCopier copier = BeanCopier.create(ServProduct.class, ProductBaseDRO.class, false);
        for (int i = 0; i < servProducts.size(); i++) {
            productBaseDRO = new ProductBaseDRO();
            copier.copy(servProducts.get(i), productBaseDRO, null);
            productBaseDRO.setServCategName(findServCategNameById(servCategories, productBaseDRO.getServCategId(), productBaseDRO.getShowType()));
            productBaseDRO.setCategOneName(findBaseCategNameById(baseCategorieall, productBaseDRO.getCategOneId()));
            productBaseDRO.setCategName(findBaseCategNameById(baseCategorieall, productBaseDRO.getCategId()));
            productBaseDROList.add(productBaseDRO);
        }

        return productBaseDROList;
    }


    @Override
    public Integer copyFromProduct(ServProductCopyVO servProductCopyVO) {
        Integer productId = servProductCopyVO.getProductId();
        // 参数检查
        if (CollectionUtils.isEmpty(servProductCopyVO.getCategIds()) || NumberUtil.isNullOrZero(productId)
                || NumberUtil.isNullOrZero(servProductCopyVO.getTitleIndex())) {
            throw new PlatException("参数缺失，请刷新后重试");
        }
        ServProduct product = servProductService.findByKey(productId);
        if (Objects.isNull(product)) {
            throw new PlatException("产品不存在");
        }
        // 产品描述
        if (Objects.equals(servProductCopyVO.getTitleIndex(), ProductTitleConstants.COPY_TYPE_PRODUCT_DESC_CODE)) {
            if (StringUtil.isBlank(product.getProductDesc())) {
                throw new PlatException("产品描述为空，不能应用到对应分类的产品中");
            }
            return servProductService.updateProductDescByCategIds(product.getProductDesc(), servProductCopyVO.getCategIds(), servProductCopyVO.getOpeator());
        }
        // 产品图片
        else if (servProductCopyVO.getTitleIndex() / 10 == 2) {
            ServProductPicture picture = servProductPictureService.findByProductId(productId);
            if (Objects.isNull(picture)) {
                throw new PlatException("产品未配置图片，不能应用到对应分类的产品中");
            }
            // 按类别处理图片，需要处理没有配置图片的数据（新增）
            return handlePicture(picture, servProductCopyVO);
        }
        //产品保障
        else if (servProductCopyVO.getTitleIndex() / 10 == 3) {
            ProductGuarantee guarantee = productGuaranteeService.findByProductId(productId);
            if (Objects.isNull(guarantee)) {
                throw new PlatException("产品未配置保障信息，不能应用到对应分类的产品中");
            }
            // 按类别处理图片，需要处理没有配置图片的数据（新增）
            return handleGuarantee(guarantee, servProductCopyVO);
        }
        return null;
    }

    private Integer handleGuarantee(ProductGuarantee guarantee, ServProductCopyVO servProductCopyVO) {
        Integer guaranteeType = servProductCopyVO.getTitleIndex();
        //根据类型获取最终修改的保障实体
        ProductGuarantee updateGuarantee = getUpdateGuarantee(guarantee, guaranteeType, servProductCopyVO.getOpeator());
        // 配置了图片或者没配置保障的产品id
        List<ShowProductIdVO> productIds = productGuaranteeService.listConfigGuaranteeProductIdByCategTwoQuery(servProductCopyVO.getCategIds());
        List<Integer> addProductGuaranteeProductIds = new ArrayList<>();
        List<Integer> updateProductGuaranteeProductIds = new ArrayList<>();
        productIds.stream().forEach(e -> {
            if (Objects.isNull(e.getConfigProductId())) {
                addProductGuaranteeProductIds.add(e.getProductId());
            } else {
                updateProductGuaranteeProductIds.add(e.getProductId());
            }
        });

        Integer result = 0;
        // 新增产品保障
        if (!CollectionUtils.isEmpty(addProductGuaranteeProductIds)) {
            List<ProductGuarantee> addGuaranteeList = addProductGuaranteeProductIds.stream().map(e -> {
                ProductGuarantee one = new ProductGuarantee();
                BeanCopyUtils.copyProperties(updateGuarantee, one);
                one.setProductId(e);
                one.setCreater(servProductCopyVO.getOpeator());
                one.setCreateTime(one.getUpdateTime());
                return one;
            }).collect(Collectors.toList());
            result = productGuaranteeService.insertBatch(addGuaranteeList);
        }

        // 修改产品保障
        if (!CollectionUtils.isEmpty(updateProductGuaranteeProductIds)) {
            result += productGuaranteeService.updateByProductIds(updateProductGuaranteeProductIds, updateGuarantee);
        }

        return result;
    }

    private ProductGuarantee getUpdateGuarantee(ProductGuarantee guarantee, Integer guaranteeType, String operator) {
        ProductGuarantee retGuarantee = new ProductGuarantee();
        retGuarantee.setUpdater(operator);
        retGuarantee.setUpdateTime(DateUtil.getNow());
        if (Objects.equals(guaranteeType, ProductTitleConstants.COPY_TYPE_PRODUCT_GURENTEE_SMALL_PIC_CODE)) {
            if (StringUtil.isBlank(guarantee.getSmallPictureOne()) && StringUtil.isBlank(guarantee.getSmallPictureTwo())
                    && StringUtil.isBlank(guarantee.getSmallPictureThree()) && StringUtil.isBlank(guarantee.getSmallPictureFour())
                    && StringUtil.isBlank(guarantee.getSmallPictureFive()) && StringUtil.isBlank(guarantee.getSmallPictureSix())
            ) {
                throw new PlatException("产品保障图片未配置，不能应用到对应分类的产品中");
            }
            retGuarantee.setSmallPictureOne(guarantee.getSmallPictureOne());
            retGuarantee.setSmallPictureOneDesc(guarantee.getSmallPictureOneDesc());
            retGuarantee.setSmallPictureTwo(guarantee.getSmallPictureTwo());
            retGuarantee.setSmallPictureTwoDesc(guarantee.getSmallPictureTwoDesc());
            retGuarantee.setSmallPictureThree(guarantee.getSmallPictureThree());
            retGuarantee.setSmallPictureThreeDesc(guarantee.getSmallPictureThreeDesc());
            retGuarantee.setSmallPictureFour(guarantee.getSmallPictureFour());
            retGuarantee.setSmallPictureFourDesc(guarantee.getSmallPictureFourDesc());
            retGuarantee.setSmallPictureFive(guarantee.getSmallPictureFive());
            retGuarantee.setSmallPictureFiveDesc(guarantee.getSmallPictureFiveDesc());
            retGuarantee.setSmallPictureSix(guarantee.getSmallPictureSix());
            retGuarantee.setSmallPictureSixDesc(guarantee.getSmallPictureSixDesc());
            return retGuarantee;
        } else if (Objects.equals(guaranteeType, ProductTitleConstants.COPY_TYPE_PRODUCT_GURENTEE_CONTENT_CODE)) {
            if (StringUtil.isBlank(guarantee.getDetail())) {
                throw new PlatException("产品保障详情未配置，不能应用到对应分类的产品中");
            }
            retGuarantee.setDetail(guarantee.getDetail());
            return retGuarantee;
        }
        return null;
    }


    private Integer handlePicture(ServProductPicture picture, ServProductCopyVO servProductCopyVO) {
        Integer pictureType = servProductCopyVO.getTitleIndex();
        //根据类型获取最终修改的图片实体
        ServProductPicture updatePicture = getUpdatePicture(picture, pictureType, servProductCopyVO.getOpeator());
        // 配置了图片或者没配置图片的产品id
        List<ShowProductIdVO> productIds = servProductPictureService.listConfigPictureProductIdByCategTwoQuery(servProductCopyVO.getCategIds());
        List<Integer> addProductPictureProductIds = new ArrayList<>();
        List<Integer> updateProductPictureProductIds = new ArrayList<>();
        productIds.stream().forEach(e -> {
            if (Objects.isNull(e.getConfigProductId())) {
                addProductPictureProductIds.add(e.getProductId());
            } else {
                updateProductPictureProductIds.add(e.getProductId());
            }
        });

        Integer result = 0;
        // 新增产品图片
        if (!CollectionUtils.isEmpty(addProductPictureProductIds)) {
            List<ServProductPicture> addPictureList = addProductPictureProductIds.stream().map(e -> {
                ServProductPicture one = new ServProductPicture();
                BeanCopyUtils.copyProperties(updatePicture, one);
                one.setProductId(e);
                one.setCreater(servProductCopyVO.getOpeator());
                one.setCreateTime(one.getUpdateTime());
                return one;
            }).collect(Collectors.toList());
            result = servProductPictureService.insertBatch(addPictureList);
        }

        // 修改产品图片
        if (!CollectionUtils.isEmpty(updateProductPictureProductIds)) {
            result += servProductPictureService.updateByProductIds(updateProductPictureProductIds, updatePicture);
        }

        return result;
    }

    private ServProductPicture getUpdatePicture(ServProductPicture picture, Integer updateType, String operator) {
        ServProductPicture retPicture = new ServProductPicture();
        retPicture.setUpdater(operator);
        retPicture.setUpdateTime(DateUtil.getNow());
        if (Objects.equals(updateType, ProductTitleConstants.COPY_TYPE_PRODUCT_SMALL_PIC_CODE)) {
            if (StringUtil.isBlank(picture.getSmallPicture())) {
                throw new PlatException("产品小图未配置，不能应用到对应分类的产品中");
            }
            retPicture.setSmallPicture(picture.getSmallPicture());
            retPicture.setSmallPictureDesc(picture.getSmallPictureDesc());
            retPicture.setSmallPictureSort(picture.getSmallPictureSort());
            return retPicture;
        } else if (Objects.equals(updateType, ProductTitleConstants.COPY_TYPE_PRODUCT_MIDDLE_PIC_CODE)) {
            if (StringUtil.isBlank(picture.getMiddlePictureOne()) && StringUtil.isBlank(picture.getMiddlePictureTwo())
                    && StringUtil.isBlank(picture.getMiddlePictureThree()) && StringUtil.isBlank(picture.getMiddlePictureFour())
                    && StringUtil.isBlank(picture.getMiddlePictureFive())) {
                throw new PlatException("产品中图未配置，不能应用到对应分类的产品中");
            }
            retPicture.setMiddlePictureOne(picture.getMiddlePictureOne());
            retPicture.setMiddlePictureOneDesc(picture.getMiddlePictureOneDesc());
            retPicture.setMiddlePictureTwo(picture.getMiddlePictureTwo());
            retPicture.setMiddlePictureTwoDesc(picture.getMiddlePictureTwoDesc());
            retPicture.setMiddlePictureThree(picture.getMiddlePictureThree());
            retPicture.setMiddlePictureThreeDesc(picture.getMiddlePictureThreeDesc());
            retPicture.setMiddlePictureFour(picture.getMiddlePictureFour());
            retPicture.setMiddlePictureFourDesc(picture.getMiddlePictureFourDesc());
            retPicture.setMiddlePictureFive(picture.getMiddlePictureFive());
            retPicture.setMiddlePictureFiveDesc(picture.getMiddlePictureFiveDesc());
            return retPicture;
        } else if (Objects.equals(updateType, ProductTitleConstants.COPY_TYPE_PRODUCT_BIG_PIC_CODE)) {
            if (StringUtil.isBlank(picture.getBigPictureOne()) && StringUtil.isBlank(picture.getBigPictureTwo())
                    && StringUtil.isBlank(picture.getBigPictureThree()) && StringUtil.isBlank(picture.getBigPictureFour())
                    && StringUtil.isBlank(picture.getBigPictureFive())) {
                throw new PlatException("产品大图未配置，不能应用到对应分类的产品中");
            }
            retPicture.setBigPictureOne(picture.getBigPictureOne());
            retPicture.setBigPictureOneDesc(picture.getBigPictureOneDesc());
            retPicture.setBigPictureOneSort(picture.getBigPictureOneSort());
            retPicture.setBigPictureTwo(picture.getBigPictureTwo());
            retPicture.setBigPictureTwoDesc(picture.getBigPictureTwoDesc());
            retPicture.setBigPictureTwoSort(picture.getBigPictureTwoSort());
            retPicture.setBigPictureThree(picture.getBigPictureThree());
            retPicture.setBigPictureThreeDesc(picture.getBigPictureThreeDesc());
            retPicture.setBigPictureThreeSort(picture.getBigPictureThreeSort());
            retPicture.setBigPictureFour(picture.getBigPictureFour());
            retPicture.setBigPictureFourDesc(picture.getBigPictureFourDesc());
            retPicture.setBigPictureFourSort(picture.getBigPictureFourSort());
            retPicture.setBigPictureFive(picture.getBigPictureFive());
            retPicture.setBigPictureFiveDesc(picture.getBigPictureFiveDesc());
            retPicture.setBigPictureFiveSort(picture.getBigPictureFiveSort());
            return retPicture;
        } else if (Objects.equals(updateType, ProductTitleConstants.COPY_TYPE_PRODUCT_VIDO_CODE)) {
            if (StringUtil.isBlank(picture.getVideoSrc())) {
                throw new PlatException("产品视频未配置，不能应用到对应分类的产品中");
            }
            retPicture.setVideoSrc(picture.getVideoSrc());
            retPicture.setVideoDesc(picture.getVideoDesc());
            return retPicture;
        } else if (Objects.equals(updateType, ProductTitleConstants.COPY_TYPE_PRODUCT_SERVICE_CODE)) {
            if (StringUtil.isBlank(picture.getShowServiceProcessPictureOne()) && StringUtil.isBlank(picture.getShowServiceProcessPictureTwo())
                    && StringUtil.isBlank(picture.getShowServiceProcessPictureThree()) && StringUtil.isBlank(picture.getShowServiceProcessPictureFour())
                    && StringUtil.isBlank(picture.getShowServiceProcessPictureFive()) && StringUtil.isBlank(picture.getShowServiceProcessPictureSix())) {
                throw new PlatException("产品服务流程图未配置，不能应用到对应分类的产品中");
            }
            retPicture.setShowServiceProcessPictureOne(picture.getShowServiceProcessPictureOne());
            retPicture.setShowServiceProcessPictureOneDesc(picture.getShowServiceProcessPictureOneDesc());
            retPicture.setShowServiceProcessPictureOneSort(picture.getShowServiceProcessPictureOneSort());
            retPicture.setShowServiceProcessPictureTwo(picture.getShowServiceProcessPictureTwo());
            retPicture.setShowServiceProcessPictureTwoDesc(picture.getShowServiceProcessPictureTwoDesc());
            retPicture.setShowServiceProcessPictureTwoSort(picture.getShowServiceProcessPictureTwoSort());
            retPicture.setShowServiceProcessPictureThree(picture.getShowServiceProcessPictureThree());
            retPicture.setShowServiceProcessPictureThreeDesc(picture.getShowServiceProcessPictureThreeDesc());
            retPicture.setShowServiceProcessPictureThreeSort(picture.getShowServiceProcessPictureThreeSort());
            retPicture.setShowServiceProcessPictureFour(picture.getShowServiceProcessPictureFour());
            retPicture.setShowServiceProcessPictureFourDesc(picture.getShowServiceProcessPictureFourDesc());
            retPicture.setShowServiceProcessPictureFourSort(picture.getShowServiceProcessPictureFourSort());
            retPicture.setShowServiceProcessPictureFive(picture.getShowServiceProcessPictureFive());
            retPicture.setShowServiceProcessPictureFiveDesc(picture.getShowServiceProcessPictureFiveDesc());
            retPicture.setShowServiceProcessPictureFiveSort(picture.getShowServiceProcessPictureFiveSort());
            retPicture.setShowServiceProcessPictureSix(picture.getShowServiceProcessPictureSix());
            retPicture.setShowServiceProcessPictureSixDesc(picture.getShowServiceProcessPictureSixDesc());
            retPicture.setShowServiceProcessPictureSixSort(picture.getShowServiceProcessPictureSixSort());
            return retPicture;
        }
        return null;
    }


}
